package indi.yume.tools.plugin;

import com.android.build.gradle.AppExtension;
import com.android.build.gradle.AppPlugin;
import com.android.build.gradle.LibraryExtension;
import com.android.build.gradle.LibraryPlugin;
import com.android.build.gradle.api.BaseVariant;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageHandler;
import org.aspectj.tools.ajc.Main;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.internal.DefaultDomainObjectSet;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.PluginCollection;
import org.gradle.api.tasks.compile.JavaCompile;

import java.io.File;
import java.util.Arrays;
import java.util.List;

class YLogPlugin implements Plugin<Project> {
    @Override
    public void apply(final Project project) {
        PluginCollection<AppPlugin> hasApp = project.getPlugins().withType(AppPlugin.class);
        PluginCollection<LibraryPlugin> hasLib = project.getPlugins().withType(LibraryPlugin.class);

        if(hasApp.size() == 0 && hasLib.size() == 0)
            throw new IllegalStateException("'android' or 'android-library' plugin required.");

        final Logger logger = project.getLogger();
        DefaultDomainObjectSet<BaseVariant> variantSet = new DefaultDomainObjectSet<BaseVariant>(BaseVariant.class);
        if(hasApp.size() != 0)
            variantSet.addAll(((AppExtension) project).getApplicationVariants());
        else
            variantSet.addAll(((LibraryExtension) project).getLibraryVariants());

//        project.getDependencies().add("debugCompile", "com.jakewharton.hugo:hugo-runtime:1.2.2-SNAPSHOT");
        project.getDependencies().add("debugCompile", "org.aspectj:aspectjrt:1.8.6");
//        project.getDependencies().add("compile", "com.jakewharton.hugo:hugo-annotations:1.2.2-SNAPSHOT");

        project.getExtensions().create("ylog", YLogExtension.class);

        for(BaseVariant variant : variantSet){
            if(!variant.getBuildType().isDebuggable()){
                logger.debug(String.format("Skipping non-debuggable build type '%s'.", variant.getBuildType().getName()));
                return;
            } else if(!((YLogExtension)project.getExtensions().getByName("ylog")).isEnabled()){
                logger.debug("YLog is not disabled.");
                return;
            }

            final JavaCompile javaCompile = (JavaCompile) variant.getJavaCompiler();
            javaCompile.doLast(new Action<Task>() {
                @Override
                public void execute(Task task) {
                    String[] args = new String[]{
                            "-showWeaveInfo",
                            "-1.5",
                            "-inpath", javaCompile.getDestinationDir().toString(),
                            "-aspectpath", javaCompile.getClasspath().getAsPath(),
                            "-d", javaCompile.getDestinationDir().toString(),
                            "-classpath", javaCompile.getClasspath().getAsPath(),
                            "-bootclasspath", listJoin(((AppExtension) project).getBootClasspath(), File.pathSeparator)
                    };
                    logger.debug("ajc args: " + Arrays.toString(args));

                    MessageHandler messageHandler = new MessageHandler(true);
                    new Main().run(args, messageHandler);
                    for(IMessage message : messageHandler.getMessages(null, true)){
                        if (message.getKind() == IMessage.ABORT
                                || message.getKind() == IMessage.ERROR
                                || message.getKind() == IMessage.FAIL) {
                            logger.error(message.getMessage(), message.getThrown());
                        } else if(message.getKind() == IMessage.WARNING) {
                            logger.warn(message.getMessage(), message.getThrown());
                        } else if(message.getKind() == IMessage.INFO) {
                            logger.info(message.getMessage(), message.getThrown());
                        } else if(message.getKind() == IMessage.DEBUG) {
                            logger.debug(message.getMessage(), message.getThrown());
                        }
                    }
                }
            });
        }
    }

    private String listJoin(List list, String separator){
        StringBuilder stringBuilder = new StringBuilder();
        for(int i = 0; i < list.size() - 1; i++) {
            String s = list.get(i).toString();
            stringBuilder.append(s)
                    .append(separator);
        }

        if(list.size() != 0)
            stringBuilder.append(list.get(list.size() - 1).toString());

        return stringBuilder.toString();
    }
}
